import { Logger } from '@nestjs/common';

/**
 * MCP工具函数集合
 */

const logger = new Logger('MCP Utils');

// ===== URI处理工具 =====

export class URIUtils {
  /**
   * 解析MCP URI
   * 支持: project://projectId/path/to/file
   */
  static parse(uri: string): {
    protocol: string;
    projectId: string;
    path: string;
    query?: Record<string, string>;
    fragment?: string;
  } {
    try {
      const url = new URL(uri);

      if (url.protocol !== 'project:') {
        throw new Error(`Unsupported protocol: ${url.protocol}`);
      }

      const hostname = url.hostname; // projectId
      const pathname = url.pathname; // /path/to/file

      // 解析查询参数
      const query: Record<string, string> = {};
      url.searchParams.forEach((value, key) => {
        query[key] = value;
      });

      return {
        protocol: url.protocol.slice(0, -1), // 移除末尾的冒号
        projectId: hostname,
        path: decodeURIComponent(pathname),
        query: Object.keys(query).length > 0 ? query : undefined,
        fragment: url.hash || undefined,
      };
    } catch (error) {
      throw new Error(`Invalid URI format: ${uri}. Expected format: project://projectId/path/to/file`);
    }
  }

  /**
   * 构建MCP URI
   */
  static build(projectId: string, path: string, query?: Record<string, string>, fragment?: string): string {
    const cleanPath = path.startsWith('/') ? path.slice(1) : path;
    let uri = `project://${projectId}/${cleanPath}`;

    if (query) {
      const searchParams = new URLSearchParams();
      Object.entries(query).forEach(([key, value]) => {
        searchParams.append(key, value);
      });
      uri += `?${searchParams.toString()}`;
    }

    if (fragment) {
      uri += `#${fragment}`;
    }

    return uri;
  }

  /**
   * 标准化路径
   */
  static normalizePath(path: string): string {
    return path.replace(/\/+/g, '/').replace(/\/$/, '') || '/';
  }

  /**
   * 获取文件扩展名
   */
  static getFileExtension(path: string): string {
    const ext = path.split('.').pop();
    return ext ? ext.toLowerCase() : '';
  }

  /**
   * 获取文件名（不含扩展名）
   */
  static getFileName(path: string): string {
    const fileName = path.split('/').pop() || '';
    const extIndex = fileName.lastIndexOf('.');
    return extIndex > 0 ? fileName.slice(0, extIndex) : fileName;
  }
}

// ===== MIME类型检测 =====

export class MIMEUtils {
  private static readonly MIME_TYPES: Record<string, string> = {
    // TypeScript/JavaScript
    'ts': 'application/typescript',
    'tsx': 'application/typescript-tsx',
    'js': 'application/javascript',
    'jsx': 'application/javascript-jsx',

    // 样式文件
    'css': 'text/css',
    'scss': 'text/x-scss',
    'sass': 'text/x-sass',
    'less': 'text/x-less',

    // 数据文件
    'json': 'application/json',
    'json5': 'application/json5',
    'xml': 'application/xml',
    'yaml': 'application/x-yaml',
    'yml': 'application/x-yaml',

    // 文档文件
    'md': 'text/markdown',
    'txt': 'text/plain',
    'doc': 'application/msword',
    'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',

    // 图片文件
    'png': 'image/png',
    'jpg': 'image/jpeg',
    'jpeg': 'image/jpeg',
    'gif': 'image/gif',
    'svg': 'image/svg+xml',
    'ico': 'image/x-icon',

    // 配置文件
    'env': 'text/plain',
    'config': 'text/plain',
    'conf': 'text/plain',
    'ini': 'text/plain',

    // 其他
    'html': 'text/html',
    'htm': 'text/html',
    'vue': 'text/x-vue',
    'svelte': 'text/x-svelte',
  };

  static getMimeType(path: string): string {
    const ext = URIUtils.getFileExtension(path);
    return this.MIME_TYPES[ext] || 'text/plain';
  }

  static isCodeFile(path: string): boolean {
    const codeExtensions = ['ts', 'tsx', 'js', 'jsx', 'vue', 'svelte'];
    return codeExtensions.includes(URIUtils.getFileExtension(path));
  }

  static isStyleFile(path: string): boolean {
    const styleExtensions = ['css', 'scss', 'sass', 'less'];
    return styleExtensions.includes(URIUtils.getFileExtension(path));
  }

  static isDataFile(path: string): boolean {
    const dataExtensions = ['json', 'json5', 'xml', 'yaml', 'yml'];
    return dataExtensions.includes(URIUtils.getFileExtension(path));
  }
}

// ===== 文件操作工具 =====

export class FileOperationUtils {
  /**
   * 验证文件路径
   */
  static validatePath(path: string): { valid: boolean; error?: string } {
    if (!path || typeof path !== 'string') {
      return { valid: false, error: 'Path must be a non-empty string' };
    }

    // 检查非法字符
    const illegalChars = /[<>:"|?*]/;
    if (illegalChars.test(path)) {
      return { valid: false, error: 'Path contains illegal characters' };
    }

    // 检查路径长度
    if (path.length > 260) {
      return { valid: false, error: 'Path too long (max 260 characters)' };
    }

    return { valid: true };
  }

  /**
   * 根据路径确定文件类型
   */
  static determineFileType(path: string): 'document' | 'type' | 'folder' | 'file' {
    const cleanPath = path.replace(/\/$/, '');

    // 目录
    if (!cleanPath.includes('.')) {
      return 'folder';
    }

    // 文档文件
    if (cleanPath.endsWith('.tsx') || cleanPath.endsWith('.doc')) {
      return 'document';
    }

    // 类型文件
    if (cleanPath.includes('/types/') || cleanPath.includes('global/') ||
        MIMEUtils.isDataFile(cleanPath) || MIMEUtils.isCodeFile(cleanPath)) {
      return 'type';
    }

    // 其他文件
    return 'file';
  }

  /**
   * 生成文件哈希值
   */
  static generateHash(content: string): string {
    const crypto = require('crypto');
    return crypto.createHash('sha256').update(content, 'utf8').digest('hex');
  }

  /**
   * 比较文件内容
   */
  static compareContent(content1: string, content2: string): boolean {
    return content1 === content2;
  }

  /**
   * 安全的文件名生成
   */
  static sanitizeFileName(fileName: string): string {
    return fileName
      .replace(/[<>:"|?*]/g, '_')
      .replace(/\s+/g, '_')
      .toLowerCase();
  }
}

// ===== 错误处理工具 =====

export class ErrorUtils {
  /**
   * 将标准错误映射为MCP错误代码
   */
  static mapToMCPError(error: any): { code: number; message: string; data?: any } {
    if (error.code && typeof error.code === 'number') {
      return {
        code: error.code,
        message: error.message,
        data: error.data,
      };
    }

    // 根据错误消息推断错误类型
    const message = error.message || error.toString();

    if (message.includes('not found') || message.includes('does not exist')) {
      return { code: -32001, message };
    }

    if (message.includes('permission') || message.includes('unauthorized') || message.includes('forbidden')) {
      return { code: -32002, message };
    }

    if (message.includes('already exists') || message.includes('duplicate')) {
      return { code: -32003, message };
    }

    if (message.includes('validation') || message.includes('invalid')) {
      return { code: -32005, message };
    }

    return { code: -32603, message };
  }

  /**
   * 创建标准错误响应
   */
  static createErrorResponse(code: number, message: string, data?: any): any {
    return {
      success: false,
      error: { code, message, data },
      _meta: {
        requestId: this.generateRequestId(),
        timestamp: Date.now(),
      },
    };
  }

  private static generateRequestId(): string {
    return `err_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
}

// ===== 批量操作工具 =====

export class BatchOperationUtils {
  /**
   * 分批处理数组
   */
  static chunk<T>(array: T[], chunkSize: number): T[][] {
    const chunks: T[][] = [];
    for (let i = 0; i < array.length; i += chunkSize) {
      chunks.push(array.slice(i, i + chunkSize));
    }
    return chunks;
  }

  /**
   * 并发控制执行
   */
  static async parallelExecute<T, R>(
    items: T[],
    executor: (item: T) => Promise<R>,
    concurrency: number = 5,
  ): Promise<Array<{ item: T; result?: R; error?: Error }>> {
    const results: Array<{ item: T; result?: R; error?: Error }> = [];

    for (const chunk of this.chunk(items, concurrency)) {
      const chunkPromises = chunk.map(async (item) => {
        try {
          const result = await executor(item);
          return { item, result };
        } catch (error) {
          return { item, error };
        }
      });

      const chunkResults = await Promise.all(chunkPromises);
      results.push(...chunkResults);
    }

    return results;
  }

  /**
   * 重试机制
   */
  static async retry<T>(
    operation: () => Promise<T>,
    maxRetries: number = 3,
    delay: number = 1000,
  ): Promise<T> {
    let lastError: Error;

    for (let i = 0; i <= maxRetries; i++) {
      try {
        return await operation();
      } catch (error) {
        lastError = error;

        if (i < maxRetries) {
          logger.warn(`Operation failed, retrying in ${delay}ms (${i + 1}/${maxRetries})`, error.message);
          await new Promise(resolve => setTimeout(resolve, delay));
          delay *= 2; // 指数退避
        }
      }
    }

    throw lastError;
  }
}

// ===== 缓存工具 =====

export class CacheUtils {
  private static cache = new Map<string, { value: any; expiry: number }>();

  /**
   * 设置缓存
   */
  static set(key: string, value: any, ttlMs: number = 300000): void { // 默认5分钟
    this.cache.set(key, {
      value,
      expiry: Date.now() + ttlMs,
    });
  }

  /**
   * 获取缓存
   */
  static get<T = any>(key: string): T | null {
    const item = this.cache.get(key);
    if (!item) return null;

    if (Date.now() > item.expiry) {
      this.cache.delete(key);
      return null;
    }

    return item.value;
  }

  /**
   * 删除缓存
   */
  static delete(key: string): void {
    this.cache.delete(key);
  }

  /**
   * 清理过期缓存
   */
  static cleanup(): void {
    const now = Date.now();
    for (const [key, item] of this.cache.entries()) {
      if (now > item.expiry) {
        this.cache.delete(key);
      }
    }
  }
}

// ===== 性能监控工具 =====

export class PerformanceUtils {
  private static timers = new Map<string, number>();

  /**
   * 开始计时
   */
  static startTimer(id: string): void {
    this.timers.set(id, Date.now());
  }

  /**
   * 结束计时并返回耗时
   */
  static endTimer(id: string): number {
    const startTime = this.timers.get(id);
    if (!startTime) return 0;

    const duration = Date.now() - startTime;
    this.timers.delete(id);

    logger.debug(`Performance: ${id} took ${duration}ms`);
    return duration;
  }

  /**
   * 内存使用情况
   */
  static getMemoryUsage(): {
    rss: number;
    heapUsed: number;
    heapTotal: number;
    external: number;
  } {
    const usage = process.memoryUsage();
    return {
      rss: usage.rss,
      heapUsed: usage.heapUsed,
      heapTotal: usage.heapTotal,
      external: usage.external,
    };
  }

  /**
   * 格式化字节大小
   */
  static formatBytes(bytes: number): string {
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    if (bytes === 0) return '0 Bytes';

    const i = Math.floor(Math.log(bytes) / Math.log(1024));
    return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
  }
}